/* interrupt.h
 * By: Ariq Chowdhury
 * Date created: March 17th 2011
 * Date modified: March 17th 2011
 */

#ifndef _XXXOS_INTERRUPT_H
#define _XXXOS_INTERRUPT_H

/*********************************/
/*** Defines**********************/
/*********************************/

/*IO Ports for the 8259 PIC*/
#define MASTER_PIC_COMMAND 0x0020
#define MASTER_PIC_DATA 0x0021
#define SLAVE_PIC_COMMAND 0x00A0
#define SLAVE_PIC_DATA 0x00A1

/* Only define clock and keyboard for now */
#define NUM_INT_VECTORS 16
#define CLK_INT 0
#define KEYBOARD_INT 1

/* End of interrupt code */
#define PIC_EOI 0x20

/* Remappings for the irq bases because the defaults
 * may conflict in protected mode
 */
#define BIOS_MASTER_VECTOR 0x08
#define BIOS_SLAVE_VECTOR 0x70
#define MASTER_VECTOR 0x50
#define SLAVE_VECTOR 0x70 /* No need to remap slave */

/* Convert int number to hardware vector */
#define BIOS_VECTOR(irq) \
  (((irq) < 8 ? BIOS_MASTER_VECTOR : BIOS_SLAVE_VECTOR) + ((irq) & 0x07))
#define VECTOR(irq) \
  (((irq) < 8 ? MASTER_VECTOR : SLAVE_VECTOR) + ((irq) & 0x07))

/* 8259 initialization words */ 
#define ICW1 0x11
#define ICW2_M MASTER_VECTOR
#define ICW2_S SLAVE_VECTOR
#define ICW3_M 0x04
#define ICW3_S 0x02
#define ICW4 0x01


/*********************************/
/***Data Types********************/
/*********************************/

typedef struct int_hook {
  unsigned char irq;
  int (*handler)(struct int_hook *);
} int_hook_t;

typedef int (*int_handler_t)(struct int_hook *);

/*********************************/
/*** Functions********************/
/*********************************/

/*Function init_PIC
 * void -> void
 * post: 8259 PIC is ready for protected mode;
         Only call this when done with BIOS;
 * return: void
 */
void init_PIC();

/*Function enable_interrupt
 * int_hook_t -> void
 * pre: hook is the interrupt hook for the interrupt to be enabled
 * post: 8259 will handle interrupts from hook's irq
 * return: void
 */
void enable_interrupt(int_hook_t* hook);

/*Function disable_interrupt
 * int_hook_t -> void
 * pre: hook is the interrupt hook to be disabled
 * post: 8259 will ignore interrupts from hook's irq
 * return: void
 */
void disable_interrupts(int_hook_t* hook);

/*Function set_int_handler
 * int_hook_t*, int, int_handler_t -> void
 * pre: irq is the irq line to be set to hook; handler is the interrupt
 *      handler for hook.
 * post: handler will be called on interrupts
 * return: void
 */
void set_int_handler(int_hook_t* hook, int irq, int_handler_t handler);

/* Function eoi
 * int -> void
 * pre: irq is the most recently handled interrupt
 * post: irq is reset and will be able to generate another interrupt
 * return : void
 */
void eoi(int irq);

/* All handlers are defined in int_handler.S */

/* handlers for exceptions (These are part of the x86 arch) */
void exc_div_by_zero();
void exc_debug();
void exc_non_maskable_interrupt();
void exc_breakpoint();
void exc_overflow();
void exc_bound_range_exceeded();
void exc_invalid_opcode();
void exc_device_not_avail();
void exc_double_fault();
void exc_coprocesssor_segment_overrun();
void exc_invalid_tss();
void exc_seg_not_present();
void exc_stack_seg_fault();
void exc_gen_protection_fault();
void exc_page_fault();
void exc_reserved();
void exc_x87fp();
void exc_alignment_check();
void exc_machine_check();
void exc_simd_fp();
void exc_security();

/* handlers for the hardware interrupts (coming from the PIC)*/
void hwint00(void);
void hwint01(void);

/* handlers for software interrupts (anyone can define one) */
void swint00(void);

#endif /*_XXXOS_INTERRUPT_H*/
